package com.kehutong.common.webchat;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.coraframework.json.JSONObject;
import org.coraframework.util.Objects;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class XmlUtil extends DefaultHandler {

	private static final String DTD_URL = "http://apache.org/xml/features/nonvalidating/load-external-dtd";

	private JSNode root;
	private JSNode current;
	
	@Override
	public void startDocument() throws SAXException {
		
	}

	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		JSNode node = new JSNode(qName, current);
		if (this.root == null) {
			this.root = node;
		} 
		this.current = node;
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		JSNode parent = current.parent();
		if (parent != null) {
			parent.toJSON(current);
		}
		current = parent;
	}

	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		final String str = new String(ch, start, length).trim();
		if (Objects.nonEmpty(str)) {
			current.setValue(str);
		}
	}
	
	public static JSONObject xml2JSON(File file) throws Exception {
		XmlUtil parse = new XmlUtil();
		
		SAXParserFactory factory = SAXParserFactory.newInstance();
		SAXParser parser = factory.newSAXParser();
		// 禁止DTD解析，避免因找不到DTD文件导致解析失败。
		parser.getXMLReader().setFeature(DTD_URL, false);
		parser.parse(file, parse);
		
		return parse.root.toJSON();
	}
	
	public static JSONObject xml2JSON(String text) throws Exception {
		return xml2JSON(new ByteArrayInputStream(text.getBytes()));
	}
	
	public static JSONObject xml2JSON(InputStream input) throws Exception {
		XmlUtil parse = new XmlUtil();
		
		SAXParserFactory factory = SAXParserFactory.newInstance();
		SAXParser parser = factory.newSAXParser();
		// 禁止DTD解析，避免因找不到DTD文件导致解析失败。
		parser.getXMLReader().setFeature(DTD_URL, false);
		parser.parse(input, parse);
		
		return parse.root.toJSON();
	}
	
//	/**
//	 * XML 字符串转 TreeMap
//	 * 
//	 * @param xmlStr
//	 * @return
//	 */
//	public static Map<String, String> xml2JSON(String xmlStr) {
//		if (Objects.isEmpty(xmlStr)) {
//			throw new IllegalArgumentException("xml is empty");
//		}
//
//		Map<String, String> map = new TreeMap<>();
//		SAXParserFactory factory = SAXParserFactory.newInstance();
//		SAXParser parser = factory.newSAXParser();
//		// 禁止DTD解析，避免因找不到DTD文件导致解析失败。
//		parser.getXMLReader().setFeature(DTD_URL, false);
//		parser.parse(is, dh);
//		Element element = document.getDocumentElement();
//		if (element != null) {
//			NodeList nodeList = element.getChildNodes();
//			for (int i = 0; i < nodeList.getLength(); i++) {
//				Node node = nodeList.item(i);
//				String nodeName = node.getNodeName();
//				String nodeText = node.getTextContent();
//				map.put(nodeName, nodeText);
//			}
//		}
//		return map;
//	}

	public static void main(String[] args) throws Exception {
		String str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
				+ "<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
				+ "	xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd\""
				+ "	version=\"3.1\">" + "	" + "	<context-param>" + "      	<param-name>loadingName</param-name>"
				+ "     	<param-value>com.youxian.wx.app.AppMain</param-value>" + "  	</context-param>"
				+ "	<listener>" + "		<listener-class>org.coraframework.boot.ContextListener</listener-class>"
				+ "	</listener> " + "	" + "	 <session-config>" + "          <session-timeout>1</session-timeout>"
				+ "     </session-config>" + "		" + "	<welcome-file-list>"
				+ "		<welcome-file>index.html</welcome-file>" + "	</welcome-file-list>" + "</web-app>";
		
		System.out.println(xml2JSON(str));
	}
	
	private static class JSNode {
		
		private final String name;
		private String value;
		private final JSNode parent;
		private JSONObject jsonObject;
		
		public JSNode(String name, JSNode parent) {
			this.name = name;
			this.parent = parent;
		}
		
		public JSNode parent() {
			return parent;
		}

		public void toJSON(JSNode child) {
			if (jsonObject == null) {
				jsonObject = new JSONObject();
			}
			
			if (Objects.nonEmpty(child.jsonObject)) {
				jsonObject.put(child.name, child.toJSON());
			} else {
				jsonObject.putAll(child.toJSON());
			}
		}
		
		public JSONObject toJSON() {
			if (jsonObject == null) {
				jsonObject = new JSONObject();
			}
			
			if (Objects.nonEmpty(value)) {
				jsonObject.put(name, value);
			}
			
			return jsonObject;
		}
		

		public void setValue(String value) {
			this.value = value;
		}
		
	}

}
